2D齒輪製作

@edit 20170511.md @language md Title: 2017Springcd第11.2週 Date: 2017-05-11 11:00 Category: Course Tags: syllabus, w11.2 Slug: 2017spring-cd Week11.2 Author: 40423150

<b><font color="red">齒輪製作 </font></b>

<!-- PELICAN_END_SUMMARY -->

<!-- 導入 Brython 標準程式庫 -->

<script src="../data/Brython-3.3.1/brython.js"></script> <script src="../data/Brython-3.3.1/brython_stdlib.js"></script>

<!-- 啟動 Brython --> <script> window.onload=function(){ // 設定 data/py 為共用程式路徑 brython({debug:1, pythonpath:['./../data/py']}); } </script>

<!-- 以下實際利用 Brython 繪圖-->

正齒輪嚙合的協同繪圖 (17t-11t):

<canvas id='gear3' width='1000' height='600'></canvas>

<script type="text/python3">

導入 browser 模組中的 document, 並設為 doc 變數

from browser import document as doc import math

deg 為角度轉為徑度的轉換因子

deg = math.pi/180.

定義 Spur 類別

class Spur(object): def init(self, ctx): self.ctx = ctx

def create_line(self, x1, y1, x2, y2, width=3, fill="red"):
    self.ctx.beginPath()
    self.ctx.lineWidth = width
    self.ctx.moveTo(x1, y1)
    self.ctx.lineTo(x2, y2)
    self.ctx.strokeStyle = fill
    self.ctx.stroke()
#
# 定義一個繪正齒輪的繪圖函式
# midx 為齒輪圓心 x 座標
# midy 為齒輪圓心 y 座標
# rp 為節圓半徑, n 為齒數
# pa 為壓力角 (deg)
# rot 為旋轉角 (deg)
# 已經針對 n 大於等於 52 齒時的繪圖錯誤修正, 因為 base circle 與齒根圓大小必須進行判斷
def Gear(self, midx, midy, rp, n=17, pa=20, color="black"):
    # 齒輪漸開線分成 15 線段繪製
    imax = 15
    # 在輸入的畫布上繪製直線, 由圓心到節圓 y 軸頂點畫一直線
    self.create_line(midx, midy, midx, midy-rp)
    # 畫出 rp 圓, 畫圓函式尚未定義
    #create_oval(midx-rp, midy-rp, midx+rp, midy+rp, width=2)
    # a 為模數 (代表公制中齒的大小), 模數為節圓直徑(稱為節徑)除以齒數
    # 模數也就是齒冠大小
    a=2*rp/n
    # d 為齒根大小, 為模數的 1.157 或 1.25倍, 這裡採 1.25 倍
    d=2.5*rp/n
    # ra 為齒輪的外圍半徑
    ra=rp+a
    # 畫出 ra 圓, 畫圓函式尚未定義
    #create_oval(midx-ra, midy-ra, midx+ra, midy+ra, width=1)
    # rb 則為齒輪的基圓半徑
    # 基圓為漸開線長齒之基準圓
    rb=rp*math.cos(pa*deg)
    # 畫出 rb 圓 (基圓), 畫圓函式尚未定義
    #create_oval(midx-rb, midy-rb, midx+rb, midy+rb, width=1)
    # rd 為齒根圓半徑
    rd=rp-d
    # 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
    # 畫出 rd 圓 (齒根圓), 畫圓函式尚未定義
    #create_oval(midx-rd, midy-rd, midx+rd, midy+rd, width=1)
    # dr 則為基圓到齒頂圓半徑分成 imax 段後的每段半徑增量大小
    # 將圓弧分成 imax 段來繪製漸開線
    # 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
    if rd&gt;rb:
        dr = (ra-rd)/imax
    else:
        dr=(ra-rb)/imax
    # tan(pa*deg)-pa*deg 為漸開線函數
    sigma=math.pi/(2*n)+math.tan(pa*deg)-pa*deg
    for j in range(n):
        ang=-2.*j*math.pi/n+sigma
        ang2=2.*j*math.pi/n+sigma
        lxd=midx+rd*math.sin(ang2-2.*math.pi/n)
        lyd=midy-rd*math.cos(ang2-2.*math.pi/n)
        for i in range(imax+1):
            # 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
            if rd&gt;rb:
                r=rd+i*dr
            else:
                r=rb+i*dr
            theta=math.sqrt((r*r)/(rb*rb)-1.)
            alpha=theta-math.atan(theta)
            xpt=r*math.sin(alpha-ang)
            ypt=r*math.cos(alpha-ang)
            xd=rd*math.sin(-ang)

            yd=rd*math.cos(-ang)
            # i=0 時, 繪線起點由齒根圓上的點, 作為起點
            if(i==0):
                last_x = midx+xd
                last_y = midy-yd
            # 由左側齒根圓作為起點, 除第一點 (xd,yd) 齒根圓上的起點外, 其餘的 (xpt,ypt)則為漸開線上的分段點
            self.create_line((midx+xpt),(midy-ypt),(last_x),(last_y),fill=color)
            # 最後一點, 則為齒頂圓
            if(i==imax):
                lfx=midx+xpt
                lfy=midy-ypt
            last_x = midx+xpt
            last_y = midy-ypt
        # the line from last end of dedendum point to the recent
        # end of dedendum point
        # lxd 為齒根圓上的左側 x 座標, lyd 則為 y 座標
        # 下列為齒根圓上用來近似圓弧的直線
        self.create_line((lxd),(lyd),(midx+xd),(midy-yd),fill=color)
        for i in range(imax+1):
            # 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
            if rd&gt;rb:
                r=rd+i*dr
            else:
                r=rb+i*dr
            theta=math.sqrt((r*r)/(rb*rb)-1.)
            alpha=theta-math.atan(theta)
            xpt=r*math.sin(ang2-alpha)
            ypt=r*math.cos(ang2-alpha)
            xd=rd*math.sin(ang2)
            yd=rd*math.cos(ang2)
            # i=0 時, 繪線起點由齒根圓上的點, 作為起點
            if(i==0):
                last_x = midx+xd
                last_y = midy-yd
            # 由右側齒根圓作為起點, 除第一點 (xd,yd) 齒根圓上的起點外, 其餘的 (xpt,ypt)則為漸開線上的分段點
            self.create_line((midx+xpt),(midy-ypt),(last_x),(last_y),fill=color)
            # 最後一點, 則為齒頂圓
            if(i==imax):
                rfx=midx+xpt
                rfy=midy-ypt
            last_x = midx+xpt
            last_y = midy-ypt
        # lfx 為齒頂圓上的左側 x 座標, lfy 則為 y 座標
        # 下列為齒頂圓上用來近似圓弧的直線
        self.create_line(lfx,lfy,rfx,rfy,fill=color)

準備在 id="gear3" 的 canvas 中繪圖

canvas = doc["gear3"] ctx = canvas.getContext("2d")

模數決定齒的尺寸大小, 囓合齒輪組必須有相同的模數與壓力角

壓力角 pa 單位為角度

pa = 20

第1齒輪齒數

n_g1 = 17

第2齒輪齒數

n_g2 = 11

m 為模數, 根據畫布的寬度, 計算適合的模數大小

m = (0.8*canvas.width)/(n_g1+n_g2)

根據模數 m, 計算各齒輪的節圓半徑

rp_g1 = mn_g1/2 rp_g2 = mn_g2/2

單一正齒輪繪圖呼叫格式 Spur(ctx).Gear(x, y, r, n, pa, "blue")

開始繪製囓合齒輪輪廓

繪圖第1齒輪的圓心座標, 因為希望繪圖佔去 canvas.width 的 80%, 所以兩邊各預留 10% 距離

x_g1 = canvas.width*0.05+rp_g1

y 方向繪圖區域上方預留 canvas.height 的 20%

y_g1 = canvas.height*0.1+rp_g1

第2齒輪的圓心座標, 假設排列成水平, 表示各齒輪圓心 y 座標相同

x_g2 = x_g1 + rp_g1 + rp_g2 y_g2 = y_g1

將第1齒輪順時鐘轉 90 度, 也就是 math.pi/2

使用 ctx.save() 與 ctx.restore() 以確保各齒輪以相對座標進行旋轉繪圖

ctx.save()

translate to the origin of second gear

ctx.translate(x_g1, y_g1)

rotate to engage

ctx.rotate(math.pi/2)

put it back

ctx.translate(-x_g1, -y_g1)

繪製第一個齒輪輪廓

Spur(ctx).Gear(x_g1, y_g1, rp_g1, n_g1, pa, "red") ctx.restore()

將第2齒輪逆時鐘轉 90 度之後, 再多轉一齒, 以便與第1齒輪進行囓合

ctx.save()

translate to the origin of second gear

ctx.translate(x_g2, y_g2)

rotate to engage

ctx.rotate(-math.pi/2-math.pi/n_g2)

put it back

ctx.translate(-x_g2, -y_g2) Spur(ctx).Gear(x_g2, y_g2, rp_g2, n_g2, pa, "black") ctx.restore()

</script>